//
// chat_message.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef CHAT_MESSAGE_HPP
#define CHAT_MESSAGE_HPP

#include <iomanip>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "log.h"

class Message
{
public:
    enum { HEADER_LEN   = 4 };
    enum { MAX_BODY_LEN = 512 };

    Message()
            : body_length_(0)
    {
        reset() ;
    }

    void reset()
    {
        std::memset(data_, 0, HEADER_LEN+MAX_BODY_LEN);
    }
    const char* data() const
    {
        return data_;
    }

    char* data()
    {
        return data_;
    }

    size_t length() const
    {
        return HEADER_LEN + body_length_;
    }

    size_t size() const
    {
        return HEADER_LEN + body_length_;
    }

    const char* body() const
    {
        return data_ + HEADER_LEN;
    }

    char* body()
    {
        return data_ + HEADER_LEN;
    }

    size_t body_length() const
    {
        return body_length_;
    }

    void body_length(size_t length)
    {
        body_length_ = length;
        if (body_length_ > MAX_BODY_LEN)
            body_length_ = MAX_BODY_LEN;
    }

    bool decode_header()
    {
        using namespace std; // For strncat and atoi.
        char header[HEADER_LEN + 1] = "";
        strncat(header, data_, HEADER_LEN);
        body_length_ = atoi(header);
        if (body_length_ > MAX_BODY_LEN)
        {
            body_length_ = 0;
            return false;
        }
        return true;
    }

    void encode_header()
    {
        using namespace std; // For sprintf and memcpy.
        char header[HEADER_LEN + 1] = "";
        sprintf(header, "%4d", body_length_);
        memcpy(data_, header, HEADER_LEN);
    }

    friend std::ostream & operator<< (std::ostream & os, const Message & msg)
    {
        os << "\n---Show Message Begin---" << std::endl ;
        char fillc = os.fill('0') ;
        os << "body len=" << msg.body_length_ << "\n" ;
        os << "content:\n" ;
        for (unsigned int i=0; i <= msg.body_length_/sizeof(unsigned int); i++)
            os << std::hex << std::setw(sizeof(unsigned int)) << *((unsigned int *)msg.data_ + i) << ' ' ;
        os << std::setfill(fillc);
        os << "\n---Show Message End---" << std::endl ;

        return os ;
    }

private:
    char data_[HEADER_LEN + MAX_BODY_LEN];
    size_t body_length_;
};

#endif // CHAT_MESSAGE_HPP
